﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using main.sdk.display.object2d;
using Microsoft.Xna.Framework;
using main.sdk.input;
using Microsoft.Xna.Framework.Input;
using FarseerPhysics.Dynamics;
using FarseerPhysics.Common;
using FarseerPhysics.Factories;

namespace main.src.game
{
    public sealed class Game_Field
    {
        public  readonly float Scale      = 12.0f;
        public  readonly World World      = new World(Vector2.Zero);
        private List<Body> FieldLimits    = new List<Body>();
        private int[]  _Limits            = { 
                                                62, 84, 
                                                962, 84, 
                                                962, 336, 
                                                1024, 336, 
                                                1024, 432, 
                                                962, 432, 
                                                962, 684, 
                                                62, 684, 
                                                62, 432,
                                                0,  432,
                                                0, 336, 
                                                62, 336,
                                                62, 84
                                            };

        private Sprite      _Sprite = new Sprite("RSC/Picture/Field");
        private Body        _Goal1 = null;
        private Body        _Goal2 = null;

        private Game_Team   _Team1  = null;
        private Game_Team   _Team2  = null;
        private Game_Ball   _Ball   = null;
        
        private double      _AccumTime = 0;

        /**
         * Construtor.
         */
        public Game_Field()
        {
            /* Cria a bola. */
            _Ball = new Game_Ball(this);
            _Team1 = new Game_Team(this);
            _Team2 = new Game_Team(this);

            /* Cria o corpo do limite da tela. */
            int Size = (_Limits.Length / 2) - 1;
            for (int i = 0; i < Size; ++i)
            {
                Vector2 Start = Vector2.Multiply(new Vector2(_Limits[i * 2], _Limits[i * 2 + 1]), 1.0f / Scale);
                Vector2 End = Vector2.Multiply(new Vector2(_Limits[(i + 1) * 2], _Limits[(i + 1) * 2 + 1]), 1.0f / Scale);

                Body b = BodyFactory.CreateEdge(this.World, Start, End);
                b.CollisionCategories = Category.All;
                b.CollidesWith = Category.All;
                b.Restitution = 0.6f;
                b.Friction = 0.4f;
                FieldLimits.Add(b);
            }

            /* Sensores do gol */
            _Goal1 = BodyFactory.CreateRectangle(this.World, 62.0f / Scale, 96.0f / Scale, 1.0f);
            _Goal1.Position = Vector2.Multiply(new Vector2(32, 384), 1.0f / Scale);
            _Goal1.IsSensor = true;
            _Goal1.OnCollision += new OnCollisionEventHandler(Goal1_OnCollision);
            _Goal2 = BodyFactory.CreateRectangle(this.World, 62.0f / Scale, 96.0f / Scale, 1.0f);
            _Goal2.IsSensor = true;
            _Goal2.Position = Vector2.Multiply(new Vector2(994, 384), 1.0f / Scale);
            _Goal2.OnCollision += new OnCollisionEventHandler(Goal2_OnCollision);

            /* */
            _Ball.Position = new Vector2(Program.Width / 2, Program.Height / 2);
            _Ball.Setup(new Vector2(3, 1), 400);

            _Sprite.OX = _Sprite.Width / 2;
            _Sprite.OY = _Sprite.Height / 2;
            _Sprite.X = Program.Width / 2;
            _Sprite.Y = Program.Height / 2;
            _Sprite.Z = -100;


            KeyWrapper Up   = (new KeyWrapper()).WrapKey(Keys.Up).WrapGamepad(0, KeyWrapper.GamePadLSUp);
            KeyWrapper Down = (new KeyWrapper()).WrapKey(Keys.Down).WrapGamepad(0, KeyWrapper.GamePadLSDown);

            Random R = new Random();

            for (int i = 0; i <= 4; ++i)
            {
                Game_Rod Rod = new Game_PlayerRod(_Team1, Up, Down, 112 + (800 / 4) * i);

                int Max = (R.Next() % 4) + 1;

                for (int j = 0; j < Max; ++j)
                {
                    Rod.AddPlayer((R.Next() % 8) * 64);
                }

                _Team1.AddRod(Rod);
            }
        }

        bool Goal2_OnCollision(Fixture fixtureA, Fixture fixtureB, FarseerPhysics.Dynamics.Contacts.Contact contact)
        {
            Console.WriteLine("Goal2");
            return true;
        }

        bool Goal1_OnCollision(Fixture fixtureA, Fixture fixtureB, FarseerPhysics.Dynamics.Contacts.Contact contact)
        {
            Console.WriteLine("Goal1");
            return true;
        }

        public void Dispose()
        {
            _Sprite.Dispose();
        }

        public void UpdateWorld(double Time)
        {
            _AccumTime += Time;
            while (_AccumTime >= 0.01)
            {
                _AccumTime -= 0.01;
                _Ball.UpdatePhysics();
                World.Step(0.01f);
                World.ClearForces();
            }
        }

        public void Update(double Time)
        {
            UpdateWorld(Time);

            _Ball.Update(Time);
            _Team1.Update(Time);
            _Team2.Update(Time);
        }
    }
}
